package org.dromara.business.service.impl;

import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import org.dromara.business.domain.Advertising;
import org.dromara.business.domain.User;
import org.dromara.business.domain.UserFlowing;
import org.dromara.business.domain.bo.UserBo;
import org.dromara.business.domain.vo.BusinessConfigVo;
import org.dromara.business.domain.vo.UserVo;
import org.dromara.business.mapper.AdvertisingMapper;
import org.dromara.business.mapper.UserMapper;
import org.dromara.business.service.BusinessConfigService;
import org.dromara.business.service.UserFlowingService;
import org.dromara.business.service.UserService;
import org.dromara.common.core.constant.UserConstants;
import org.dromara.common.core.exception.ServiceException;
import org.dromara.common.core.utils.MapstructUtils;
import cn.hutool.core.util.StrUtil;
import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.common.mybatis.core.page.PageQuery;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import lombok.RequiredArgsConstructor;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.dromara.common.satoken.utils.LoginHelper;
import org.dromara.common.translation.core.impl.DictTypeTranslationImpl;
import org.dromara.common.websocket.utils.WebSocketUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.*;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

/**
 * 用户信息Service业务层处理
 *
 * @author zlj
 * @date 2024-11-19
 */
@RequiredArgsConstructor
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {

    private final UserMapper baseMapper;
    private final DictTypeTranslationImpl dictTypeTranslation;
    private final BusinessConfigService businessConfigService;
    private final UserFlowingService userFlowingService;
    private final AdvertisingMapper advertisingMapper;
    private final ScheduledExecutorService scheduledExecutorService;

    /**
     * 查询用户信息
     */
    @Override
    public UserVo queryById(Long userId) {
        UserVo userVo = baseMapper.selectVoById(userId);
        String userType = dictTypeTranslation.translation(userVo.getType(), "user_type");
        userVo.setTypeName(userType);
        return userVo;
    }

    /**
     * 查询用户信息列表
     */
    @Override
    public TableDataInfo<UserVo> queryPageList(UserBo bo, PageQuery pageQuery) {
        LambdaQueryWrapper<User> lqw = buildQueryWrapper(bo);
        Page<UserVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);

        for (UserVo record : result.getRecords()) {
            String userType = dictTypeTranslation.translation(record.getType(), "user_type");
            record.setTypeName(userType);
        }
        return TableDataInfo.build(result);
    }

    /**
     * 查询用户信息列表
     */
    @Override
    public List<UserVo> queryList(UserBo bo) {
        LambdaQueryWrapper<User> lqw = buildQueryWrapper(bo);
        return baseMapper.selectVoList(lqw);
    }

    private LambdaQueryWrapper<User> buildQueryWrapper(UserBo bo) {
        Map<String, Object> params = bo.getParams();
        LambdaQueryWrapper<User> lqw = Wrappers.lambdaQuery();
        lqw.eq(bo.getDeptId() != null, User::getDeptId, bo.getDeptId());
        lqw.like(StrUtil.isNotBlank(bo.getUserName()), User::getUserName, bo.getUserName());
        lqw.like(StrUtil.isNotBlank(bo.getNickName()), User::getNickName, bo.getNickName());
        lqw.eq(StrUtil.isNotBlank(bo.getUserType()), User::getUserType, bo.getUserType());
        lqw.eq(StrUtil.isNotBlank(bo.getEmail()), User::getEmail, bo.getEmail());
        lqw.eq(StrUtil.isNotBlank(bo.getPhonenumber()), User::getPhonenumber, bo.getPhonenumber());
        lqw.eq(StrUtil.isNotBlank(bo.getOpenid()), User::getOpenid, bo.getOpenid());
        lqw.eq(StrUtil.isNotBlank(bo.getUnionid()), User::getUnionid, bo.getUnionid());
        lqw.eq(StrUtil.isNotBlank(bo.getSex()), User::getSex, bo.getSex());
        lqw.eq(bo.getAvatar() != null, User::getAvatar, bo.getAvatar());
        lqw.eq(StrUtil.isNotBlank(bo.getPassword()), User::getPassword, bo.getPassword());
        lqw.eq(bo.getAmount() != null, User::getAmount, bo.getAmount());
        lqw.eq(bo.getAllAmount() != null, User::getAllAmount, bo.getAllAmount());
        lqw.eq(StrUtil.isNotBlank(bo.getStatus()), User::getStatus, bo.getStatus());
        lqw.eq(StrUtil.isNotBlank(bo.getLoginIp()), User::getLoginIp, bo.getLoginIp());
        lqw.eq(StrUtil.isNotBlank(bo.getIsProxy()), User::getIsProxy, bo.getIsProxy());
        lqw.eq(bo.getLoginDate() != null, User::getLoginDate, bo.getLoginDate());
        lqw.eq(bo.getQrCode() != null, User::getQrCode, bo.getQrCode());
        lqw.eq(bo.getSuperiorId() != null, User::getSuperiorId, bo.getSuperiorId());
        lqw.eq(StrUtil.isNotBlank(bo.getWxAvatar()), User::getWxAvatar, bo.getWxAvatar());
        lqw.orderByDesc(User::getCreateTime);
        return lqw;
    }

    /**
     * 新增用户信息
     */
    @Override
    public Boolean insertByBo(UserBo bo) {
        User add = MapstructUtils.convert(bo, User.class);
        validEntityBeforeSave(add);
        boolean flag = baseMapper.insert(add) > 0;
        if (flag) {
            bo.setUserId(add.getUserId());
        }
        return flag;
    }

    /**
     * 修改用户信息
     */
    @Override
    public Boolean updateByBo(UserBo bo) {
        User update = MapstructUtils.convert(bo, User.class);
        validEntityBeforeSave(update);
        if ("3".equals(update.getProxyApprovalStatus())) {
            /**
             * 审核成功讲用户状态修改
             */
            update.setIsProxy("1");

        }


        return baseMapper.updateById(update) > 0;
    }

    /**
     * 保存前的数据校验
     */
    private void validEntityBeforeSave(User entity) {

    }

    /**
     * 批量删除用户信息
     */
    @Override
    public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
        if (isValid) {

        }
        return baseMapper.deleteBatchIds(ids) > 0;
    }

    @Override
    public Boolean authentication(UserBo bo) {
        Long userId = LoginHelper.getUserId();
        User update = MapstructUtils.convert(bo, User.class);
        //将审批状态修改成待审批
        update.setUserId(userId);
        int i = baseMapper.updateById(update);
        scheduledExecutorService.schedule(() -> {
            WebSocketUtils.sendMessage(UserConstants.SUPER_ADMIN_ID, "用户+" + userId + "提出了实名认证");
        }, 0, TimeUnit.SECONDS);
        return i > 0;
    }

    @Override
    public int becomeAgent(UserBo bo) {
        Long userId = LoginHelper.getUserId();

        // 获取用户信息
        UserVo userVo = baseMapper.selectVoById(userId);
        if (userVo == null || ("0".equals(userVo.getType()) || ObjectUtil.isEmpty(userVo.getType()))) {
            throw new ServiceException("您尚未完成实名认证，请先完成实名认证。");
        }
        if ("1".equals(userVo.getIsProxy())) {
            throw new ServiceException("已经成为" + userVo.getProxyRegion() + "代理！");
        }
        // 检查代理区域是否为空
        if (ObjectUtil.isNull(bo.getProxyRegion())) {
            throw new ServiceException("代理区域不能为空，请填写代理区域。");
        }
        User user = selectByProxyRegion(bo.getProxyRegion());
        if (user != null) {
            throw new ServiceException(bo.getProxyRegion() + "已经被其他人代理了。");
        }
        // 准备更新数据
        User updateUser = MapstructUtils.convert(bo, User.class);
        updateUser.setUserId(userId);
        updateUser.setProxyApprovalStatus("2"); // 设置审批状态为待审批（注意属性名可能需要根据实际情况调整）

        // 处理代理区域
//        String newProxyRegion = (ObjectUtil.isNotNull(userVo.getProxyRegion()) ? userVo.getProxyRegion() + "," : "") + bo.getProxyRegion();
        updateUser.setProxyRegion(bo.getProxyRegion());

        // 执行更新操作并返回结果
        int i = baseMapper.updateById(updateUser);

        scheduledExecutorService.schedule(() -> {
            WebSocketUtils.sendMessage(UserConstants.SUPER_ADMIN_ID, "用户+" + bo.getCreateBy() + "申请成为代理");
        }, 0, TimeUnit.SECONDS);
        return i;
    }

    @Override
    public TableDataInfo<UserVo> getApprovalList(UserBo bo, PageQuery pageQuery) {
        Long userId = LoginHelper.getUserId();
        User byId = this.getById(userId);
        String proxyRegion = byId.getProxyRegion();
        List<String> list = Arrays.stream(proxyRegion.split(",")).toList();


        LambdaQueryWrapper<User> lqw = Wrappers.lambdaQuery();
        lqw.eq(StrUtil.isNotBlank(bo.getIfCardReview()), User::getIfCardReview, bo.getIfCardReview());
        lqw.eq(StrUtil.isNotBlank(bo.getUserType()), User::getUserType, bo.getUserType());
        lqw.eq(StrUtil.isNotBlank(bo.getIsProxy()), User::getIsProxy, bo.getIsProxy());
        lqw.eq(StrUtil.isNotBlank(bo.getProxyApprovalStatus()), User::getProxyApprovalStatus, bo.getProxyApprovalStatus());
        lqw.in(User::getCity, list);
        Page<UserVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);


        for (UserVo record : result.getRecords()) {

            String userType = dictTypeTranslation.translation(record.getType(), "user_type");
            record.setTypeName(userType);
        }
        return TableDataInfo.build(result);
    }

    /**
     * 修改发布次数
     */
    @Override
    public void upbateUserpublishCount() {
        //新增广告同步
        Long userId = LoginHelper.getUserId();
        User user = this.getById(userId);
//            if (user.getPublishCount()<=0){
//                throw new ServiceException("您的发布次数已用完。");
//            }
//            user.setPublishCount(user.getPublishCount()-1);
        baseMapper.updateById(user);
    }


    @Override
    public Boolean proxyApproval(UserBo bo) {
        User update = MapstructUtils.convert(bo, User.class);
        if ("3".equals(update.getProxyApprovalStatus())) {
            /**
             * 审核成功讲用户状态修改
             */
            update.setIsProxy("1");
            //新增发布次数
//            String key = configService.queryValueByKey("proxy_publishing_frequency");
//            update.setPublishCount(Integer.parseInt(key));
            // 计算当前时间加上指定天数后的时间
            LocalDateTime currentTime = LocalDateTime.now();
            LocalDateTime newTime = currentTime.plusDays(730);
            Date gqTime = Date.from(newTime.atZone(ZoneId.systemDefault()).toInstant());
            update.setApprovalTime(gqTime);
        }
        return baseMapper.updateById(update) > 0;
    }

    @Override
    public Boolean upbateUserVip(UserBo bo) {
        // 获取刷新次数
        User update = MapstructUtils.convert(bo, User.class);
        getRefreshTimes(update);

        return baseMapper.updateById(update) > 0;
    }

    /**
     * 根据代理城市查询代理人
     *
     * @param city
     * @return
     */
    @Override
    public User selectByProxyRegion(String city) {
        if (ObjectUtil.isNull(city)) {
            return null;
        }

        LambdaQueryWrapper<User> lqw = Wrappers.lambdaQuery();
        // 如果city不为空，则添加LIKE查询条件,是代理且代理审核通过
        lqw.like(User::getProxyRegion, city);
        lqw.eq(User::getIsProxy, "1");
        lqw.eq(User::getProxyApprovalStatus, "3");
        return baseMapper.selectOne(lqw);
    }

    /**
     * @param user
     */
    private void getRefreshTimes(User user) {

        List<BusinessConfigVo> vipList = businessConfigService.queryByKey("vip");

        // 使用 Optional 来处理可能的空流
        Optional<BusinessConfigVo> optionalBusinessConfigVo = vipList.stream()
            .filter(o -> user.getVip().equals(o.getSortNo().toString()))
            .findFirst();

        if (optionalBusinessConfigVo.isPresent()) {
            BusinessConfigVo businessConfigVo = optionalBusinessConfigVo.get();
            String remark = businessConfigVo.getRemark();

            try {
                // 使用正则表达式确保 remark 格式正确，避免 ArrayIndexOutOfBoundsException
                String[] parts = remark.split("-", 2); // 限制最多分割为两部分
                if (parts.length == 2) {
                    int hyNumber = Integer.parseInt(parts[0]);
                    int refreshTimes = Integer.parseInt(parts[1]);

                    user.setHyNumber(hyNumber);
                    user.setRefreshTimes(refreshTimes);
                } else {
                    // 处理 remark 格式不正确的情况
                    throw new IllegalArgumentException("VIP信息里面+" + user.getVip() + "的备注格式不对" + remark + "正确格式5-5-5，发布次数-置顶次数-价格");
                }
            } catch (NumberFormatException e) {
                // 处理数字格式不正确的情况
                throw new IllegalArgumentException("VIP信息里面+" + user.getVip() + "的备注格式不对" + remark + "正确格式5-5-5，发布次数-置顶次数-价格");
            }
        } else {
            // 处理未找到匹配的 VIP 配置的情况
            // 可以选择抛出异常、记录日志或设置默认值
            throw new IllegalArgumentException("VIP信息里面+" + user.getVip() + "的备注格式不对正确格式5-5-5，发布次数-置顶次数-价格");
        }
    }

    /**
     * @param bo
     * @param pageQuery
     * @return
     */
    @Override
    public TableDataInfo<UserVo> agentUserList(UserBo bo, PageQuery pageQuery) {

        LambdaQueryWrapper<User> lqw = Wrappers.lambdaQuery();

        lqw.eq(StrUtil.isNotBlank("1"), User::getIsProxy, "1");
        lqw.eq(StrUtil.isNotBlank(bo.getNickName()), User::getNickName, bo.getNickName());
        lqw.eq(StrUtil.isNotBlank(bo.getProxyRegion()), User::getProxyRegion, bo.getProxyRegion());

        Page<UserVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);

        for (UserVo record : result.getRecords()) {
            long count = countPeopleByProductionAndRegion(record.getProxyRegion());
            record.setNumberPeople(count);
            //根据开始时间和结束时间获取总收入
            BigDecimal totalRevenue = getTotalRevenue(record.getUserId(), bo);
            record.setTotalRevenue(totalRevenue);
            // 获取每个地区的广告数量
            Long adNumber = getCityNumber(record.getProxyRegion());
            record.setAdNumber(adNumber);
        }

        return TableDataInfo.build(result);
    }

    private Long getCityNumber(String city) {
        LambdaQueryWrapper<Advertising> lqw = Wrappers.lambdaQuery();
        lqw.eq(Advertising::getCity, city);
        lqw.eq(Advertising::getState, "2");

        return advertisingMapper.selectCount(lqw);

    }

    @Override
    public Boolean verifyIdentityApproval(UserBo bo) {
        User update = MapstructUtils.convert(bo, User.class);
        validEntityBeforeSave(update);
        return baseMapper.updateById(update) > 0;
    }

    @Override
    public Boolean proxyInvalidation(UserBo bo) {
        UpdateWrapper<User> update = Wrappers.update();
        update.lt("user_id", bo.getUserId());
        update.set("proxy_region", null);
        update.set("proxy_approval_status", "0");
        return baseMapper.update(null, update.set("is_proxy", '0')) >= 0;
    }

    /**
     * 积分兑换
     *
     * @param number
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public int redeem(Integer number) {
        // 验证输入
        if (number == null || number <= 0) {
            throw new IllegalArgumentException("兑换数量必须为正整数。");
        }

        // 1: 获取当前用户的ID和用户信息
        Long userId = LoginHelper.getUserId();
        User user = this.getById(userId);
        if (user == null) {
            throw new IllegalStateException("未找到用户。");
        }

        // 2: 从配置中获取每个兑换单位所需的积分
        String configValue = businessConfigService.queryValueByKey("redeem");
        try {
            int pointsPerUnit = Integer.parseInt(configValue);
            int totalPointsRequired = number * pointsPerUnit;

            // 3: 检查用户是否有足够的积分
            if (user.getPoints() >= totalPointsRequired) {
                // 4: 扣除积分并更新刷新次数
                user.setPoints(user.getPoints() - totalPointsRequired);
                user.setRedeemNumer(user.getRedeemNumer() + number);

                // 5: 更新用户信息
                int updateResult = baseMapper.updateById(user);
                if (updateResult > 0) {
                    return updateResult; // 通常期望返回1表示成功更新
                } else {
                    throw new RuntimeException("用户更新失败。");
                }
            } else {
                return -1; // 积分不足
            }
        } catch (NumberFormatException e) {
            throw new IllegalStateException("配置值'redeem'不是有效的整数。", e);
        }
    }

    @Override
    public TableDataInfo<UserVo> getMyTeam(UserBo bo, PageQuery pageQuery) {
        Long userId = LoginHelper.getUserId();
        User byId = this.getById(userId);

        LambdaQueryWrapper<User> lqw = Wrappers.lambdaQuery();


        lqw.ne(User::getUserId,userId);
        lqw.eq(StrUtil.isNotBlank(byId.getProxyRegion()), User::getCity, byId.getProxyRegion());

        Page<UserVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
        return TableDataInfo.build(result);
    }

    private BigDecimal getTotalRevenue(Long id, UserBo bo) {
        // 使用 userFlowingService 的 lambdaQuery 构建器来创建查询
        List<UserFlowing> list = userFlowingService.lambdaQuery()
            .eq(UserFlowing::getCreateBy, id) // 添加条件：创建者ID等于给定的id
            .between( // 添加时间范围条件
                bo.getParams().get("beginTime") != null && bo.getParams().get("endTime") != null, // 检查开始时间和结束时间是否都不为空
                UserFlowing::getCreateTime, // 要比较的字段：创建时间
                bo.getParams().get("beginTime"), // 开始时间
                bo.getParams().get("endTime") // 结束时间
            )
            .select(UserFlowing::getAmount) // 选择要查询的字段：金额
            .list(); // 执行查询并返回结果列表

        // 计算金额字段的总和
        BigDecimal totalAmount = list.stream()
            .map(UserFlowing::getAmount) // 将每个 UserFlowing 对象的金额提取出来
            .reduce(BigDecimal.ZERO, BigDecimal::add); // 使用 reduce 方法计算总和，初始值为 BigDecimal.ZERO

        return totalAmount; // 返回计算得到的总金额
    }

    /**
     * 获取代理区域的人数
     *
     * @param proxyRegion
     * @return
     */
    private long countPeopleByProductionAndRegion(String proxyRegion) {
        Long count = this.lambdaQuery().eq(User::getCity, proxyRegion).count();
        return count;
    }
}
